<template>
  <div
    id="float-menu-wrap"
    :style="{
      right: config.right ? config.right : null,
      bottom: config.bottom ? config.bottom : null,
    }"
  >
    <template v-if="columns.length == 1">
      <div
        :style="columns[0].colProps || {}"
        class="to-single"
        @click="jumpClick(columns[0])"
      >
        {{ columns[0].title }}
      </div>
    </template>
    <template v-else>
      <div id="conceal-container">
        <div
          v-for="(column, index) in columns"
          :key="index"
          :style="column.colProps"
          class="to-jump"
          @click="jumpClick(column)"
        >
          {{ column.title }}
        </div>
      </div>
      <div id="conceal-controller" @click="handleClick">
        {{ expandTimer ? "收起" : "展开" }}
      </div>
    </template>
  </div>
</template>

<script>
export default {
  props: {
    columns: {
      type: Array,
      default: () => [],
    },
    config: {
      type: Object,
      default: () => ({
        right: "20px",
        bottom: "80px",
      }),
    },
  },
  data() {
    return {
      element: null,
      expandTimer: null,
      collapseTimer: null,
      offsetHeight: 0,
      stepHeight: 0,
    };
  },
  methods: {
    jumpClick(column) {
      try {
        column.onClick && column.onClick();
      } catch (error) {
        console.log(error);
      }
    },
    handleClick() {
      // 如果当前 expandTimer 值存在，就标识当前是正在展开或已经展开，接下来要进行的是收起操作
      if (this.expandTimer) {
        clearInterval(this.expandTimer);
        this.expandTimer = null;
        // 收起时的初始高度是元素的当前实际高度，即使是元素在展开动画过程中，也要从当前元素高度进行收起动画
        let height = this.element.offsetHeight;

        this.collapseTimer = setInterval(() => {
          height -= this.stepHeight;
          if (height <= 0) {
            // 高度小于等于 0 代表动画完成，将数据进行重置
            clearInterval(this.collapseTimer);
            this.offsetHeight = 0;
            // 要将元素的高度置为 null，不然会影响下一次展开时获取正确的高度
            this.element.style.height = null;
            // display 设为 null，要将元素隐藏
            this.element.style.display = "none";
            return;
          }
          this.element.style.height = height + "px";
        }, 10);
      } else {
        clearInterval(this.collapseTimer);
        this.collapseTimer = null;
        // 获取元素总高度
        this.element.style.display = "block";
        let height = 0;
        // 如果当前没有 offsetHeight 就要重新获取
        if (!this.offsetHeight) {
          this.offsetHeight = this.element.offsetHeight;
          // 每一次给元素添加或减少的高度，除以 30 是自己设定的，跟下面定时器的每次间隔时间一起控制整个高度动画的时长，也可以给函数添加第二个时间参数，可以自由控制动画时间
          this.stepHeight = this.offsetHeight / 30;
        } else {
          // 如果有 offsetHeight 就代表正在进行收起动画，应该从收起动画的当前高度进行展开动画
          height = this.element.offsetHeight;
        }

        this.element.style.height = height + "px";

        this.expandTimer = setInterval(() => {
          height += this.stepHeight;
          if (height >= this.offsetHeight) {
            // 当前高度如果已经到了元素的实际高度，就要清除定时器
            clearInterval(this.expandTimer);
            // 将 expandTimer 设为 1 是因为当前是以 expandTimer 判断是否正在或已经进行了展开动画，所以要在完成是设为 1，在收起动画的开始时会将值设为 null
            this.expandTimer = 1;
            this.element.style = null;
            return;
          }
          this.element.style.height = height + "px";
        }, 10);
      }
    },
  },
  activated() {
    this.element = document.getElementById("conceal-container");
    if (this.expandTimer==1) {
      this.element.style.height = null;
      this.element.style.display = "block";
    }else{
      this.element.style.display = "none";
    }
  },
  mounted() {
    this.element = document.getElementById("conceal-container");
    if (this.element) {
      this.element.style.height = null;
      // display 设为 null，要将元素隐藏
      this.element.style.display = "none";
    }
  },
};
</script>

<style>
#float-menu-wrap {
  position: fixed;
  z-index: 1999;
  color: #ffffff;
  text-align: center;
  font-size: 13px;
  right: 20px;
  bottom: 80px;
}

#conceal-container {
  display: grid;
  /* grid-template-rows: 0fr; */
  overflow: hidden;
  transition: all 0.1s;
  z-index: 1999;
  box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.08);
  text-align: center;
  line-height: 50px;
  font-size: 13px;
  opacity: 0.9;
}
.to-single {
  width: 50px;
  height: 50px;
  border-radius: 25px;
  background: #020d23;
  color: #ffffff;
  box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.08);
  text-align: center;
  line-height: 50px;
  font-size: 13px;
  opacity: 0.9;
}
#conceal-container .to-jump {
  width: 50px;
  height: 50px;
  border-radius: 25px;
  background: #020d23;
  color: #ffffff;
  box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.08);
  text-align: center;
  line-height: 50px;
  font-size: 13px;
  opacity: 0.9;
  margin-bottom: 12px;
}
#conceal-controller {
  width: 50px;
  height: 50px;
  border-radius: 25px;
  background: #1a13a6;
  color: #ffffff;
  box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.08);
  text-align: center;
  line-height: 50px;
  font-size: 13px;
  opacity: 0.9;
}
</style>